#include "CDXMeshManager.h"
#include <string.h>

#if _DEBUG
#define _LOGGER_
#endif
#include "Logger.h"

CDXMeshManager CDXMeshManager::m_instance;

CDXMeshManager::CDXMeshManager()
{
	
}

CDXMeshManager::CDXMeshManager(const CDXMeshManager& rhs)
{

}

CDXMeshManager& CDXMeshManager::operator=(const CDXMeshManager& rhs)
{
	return *this;
}

CDXMeshManager::~CDXMeshManager()
{
	Shutdown();
}

IDXMesh* CDXMeshManager::GetMeshByID(int MeshID)
{
	for (unsigned int i = 0; i < m_meshes.size(); ++i)
	{
		if (MeshID == m_meshes[i]->GetMeshID())	
		{
			return m_meshes[i];
		}
	}
	return NULL;
}

IDXMesh* CDXMeshManager::GetMeshByName(char* MeshName)
{
	return NULL;
}

bool CDXMeshManager::Init(char* szMeshDirectory, IDirect3DDevice9* pDXDevice)
{
	strcpy_s(m_Dir, MAX_PATH, szMeshDirectory);
	m_pDevice = pDXDevice;
	return true;
}

bool CDXMeshManager::Shutdown()
{
	if (m_meshes.size() > 0)
	{
		for (unsigned int i = 0; i < m_meshes.size(); ++i)
		{
			while(m_meshes[i]->m_ref > 0)
				m_meshes[i]->DeleteMesh();
		}
		m_meshes.clear();
		Logger::OutputToVS("CDXMeshManager", "All Meshes Unloaded. Shutdown complete.");
	}

	return true;
}

int	CDXMeshManager::LoadNewDirectXMesh(char* FileName)
{
	if (!FileName)
		return -1;

	// Make sure the mesh isn't already loaded.
	for (unsigned int i = 0; i < m_meshes.size(); ++i)
	{
		// compare strings without caring about upper or lowercase.
		if (_stricmp(FileName, m_meshes[i]->GetMeshName()) == 0)	// 0 means they are equal.
		{
			m_meshes[i]->m_ref++; // add a reference to this Mesh.
#ifdef _LOGGER_
			char buffer[128];
			sprintf_s(buffer, 128, "XFile %s loaded into index %u. Mesh now has %u references.", 
				FileName, m_meshes[i]->GetMeshID(), m_meshes[i]->m_ref);
			Logger::OutputToVS("CDXMeshManager", buffer);
#endif
			return i;	// return the index.
		}
	}

	// Look for an open spot.
	int nID = -1;
	for (unsigned int i = 0; i < m_meshes.size(); i++)
	{
		if (m_meshes[i]->m_ref == 0)
		{
			nID = i;
			break;
		}
	}

	// Load the mesh
	CDXDirectXMesh* mesh = new CDXDirectXMesh();
	std::string dir = std::string(m_Dir);
	dir.append(FileName);
	mesh->LoadMesh(dir.c_str(), m_pDevice);
	mesh->SetMeshName(FileName);
	// No open spots
	if (nID == -1)
	{
		m_meshes.push_back(mesh);
		m_meshes.back()->SetMeshID((UINT)(m_meshes.size()-1));
#ifdef _LOGGER_
		char buffer[128];
		sprintf_s(buffer, 128, "XFile %s loaded into index %u", FileName, m_meshes.back()->GetMeshID());
		Logger::OutputToVS("CDXMeshManager", buffer);
#endif
		return m_meshes.back()->GetMeshID();
	}
	// Found an open spot
	else
	{
		//Make sure the spot has been unloaded correctly
		m_meshes[nID]->DeleteMesh();

		m_meshes[nID] = mesh;

#ifdef _LOGGER_
		char buffer[128];
		sprintf_s(buffer, 128, "XFile %s loaded into index %n.", FileName, nID);
		Logger::OutputToVS("CDXMeshManager", buffer);
#endif

		return nID;
	}
}

int CDXMeshManager::LoadUserDefinedMesh(CDXUserMesh* userMesh)
{
	if (!userMesh)
		return -1;

	// Make sure the texture isn't already loaded.
	for (unsigned int i = 0; i < m_meshes.size(); ++i)
	{
		// compare strings without caring about upper or lowercase.
		if (_stricmp(userMesh->GetMeshName(), m_meshes[i]->GetMeshName()) == 0)	// 0 means they are equal.
		{
			m_meshes[i]->m_ref++; // add a reference to this texture.
#ifdef _LOGGER_
			char buffer[128];
			sprintf_s(buffer, 128, "UserMesh %s loaded into index %u. Mesh now has %u references.", 
				userMesh->GetMeshName(), m_meshes[i]->GetMeshID(), m_meshes[i]->m_ref);
			Logger::OutputToVS("CDXMeshManager", buffer);
#endif
			return i;	// return the index.
		}
	}

	// Look for an open spot.
	int nID = -1;
	for (unsigned int i = 0; i < m_meshes.size(); i++)
	{
		if (m_meshes[i]->m_ref == 0)
		{
			nID = i;
			break;
		}
	}

	// Load the mesh
	// No open spots
	if (nID == -1)
	{
		m_meshes.push_back(userMesh);
		m_meshes.back()->SetMeshID((UINT)(m_meshes.size()-1));
#ifdef _LOGGER_
		char buffer[128];
		sprintf_s(buffer, 128, "Usermesh %s loaded into index %u", userMesh->GetMeshName(), m_meshes.back()->GetMeshID());
		Logger::OutputToVS("CDXMeshManager", buffer);
#endif
		return m_meshes.back()->GetMeshID();
	}
	// Found an open spot
	else
	{
		//Make sure the spot has been unloaded correctly
		m_meshes[nID]->DeleteMesh();

		m_meshes[nID] = userMesh;

#ifdef _LOGGER_
		char buffer[128];
		sprintf_s(buffer, 128, "Usermesh %s loaded into index %n", userMesh->GetMeshName(), nID);
		Logger::OutputToVS("CDXMeshManager", buffer);
#endif
		return nID;
	}
}

void CDXMeshManager::UnloadMesh(UINT nID)
{
	for (unsigned int i = 0; i < m_meshes.size(); ++i)
	{
		// compare strings without caring about upper or lowercase.
		if (nID == m_meshes[i]->GetMeshID())	// 0 means they are equal.
		{
#ifdef _LOGGER_
			char NameBuffer[16];
			strcpy_s(NameBuffer, 16, m_meshes[i]->GetMeshName());
#endif
			m_meshes[i]->DeleteMesh();
#ifdef _LOGGER_
			char buffer[128];
			sprintf_s(buffer, 128, "Mesh %s has been unloaded. %n References left", NameBuffer, m_meshes.back()->m_ref);
			Logger::OutputToVS("CDXMeshManager", buffer);
#endif
			return;
		}
	}
}


//D3DXCreateTeapot();
//D3DXCreateCylinder();
//D3DXCreateSphere();
//D3DXCreateTorus();
//D3DXCreatePolygon();
//
//int CDXMeshManager::CreateCubeMesh()
//{
//
//}
//
//int CDXMeshManager::CreateTeapot()
//{
//
//}
//
//int CDXMeshManager::CreateCylinder()
//{
//
//}
//
//int CDXMeshManager::CreateSphere()
//{
//
//}
//
//int CDXMeshManager::CreateTorus()
//{
//
//}
//
//int CDXMeshManager::CreatePolygon()
//{
//
//}

#if _DEBUG
#undef _LOGGER_
#endif